#ifndef BOXBASETYPES_H_JM_20120923
#define BOXBASETYPES_H_JM_20120923
/// @file BoxBaseTypes.h _OK_ Premenovanie zakladny typov boboxu pouzivanych 
/// v programe (kompatibilita roznych verzii boboxu).

// ## c++
#include <ostream>

// ## bobox
#include <bobox_box.hpp>
#include <bobox_types.hpp>
#include <bobox_parameters.hpp>
// ## jmlib
#include <jmlib/cast.h>

#ifndef BOBOX_VERSION_OLD
	#include <bobox_group_box.hpp>
#endif

namespace jm4bbx {

	template<class Key>
	class KeyRecord {
	public:
		typedef Key KeyType;
		KeyRecord() { }
		KeyRecord(size_t i, const KeyType& k) : index_(i), key_(k) { }

		size_t getIndex() const { return index_; }
		Key getKey() const { return key_; }
		Key* getKeyPtr() { return &key_; }

	private:
		size_t index_;
		Key key_;

	};


	template<typename Key>
	class KeyMultiRecords {
	public:
		//	void a(const std::string& x) { actBuff_ += x; }


		typedef Key KeyType;
		typedef std::set<size_t> IndexContainer;
		typedef IndexContainer::iterator iterator;
		typedef IndexContainer::const_iterator const_iterator;
		
		KeyMultiRecords(): valid_(true) { /*a("c1");*/ }
		KeyMultiRecords(const KeyType& k) : key_(k), valid_(true) { /*a("c2");*/ }
		KeyMultiRecords(size_t i, const KeyType& k) : key_(k), valid_(true) {
			 //a("c3"); 
			indices_.insert(i);
		}	

		virtual ~KeyMultiRecords() { }

		iterator begin() { return indices_.begin(); }
		iterator end() { return indices_.end(); }
		const_iterator begin() const { return indices_.begin(); }
		const_iterator end() const { return indices_.end(); }

		void insert(size_t index) {  
			//a(jmlib::convert<std::string>(index) + "i"); 
			indices_.insert(index); 
		}

		size_t size() const { return indices_.size(); }
		bool isEmpty() const { return indices_.empty(); }
		void erase(iterator it) { 
			//a("e"); 
			indices_.erase(it); 
		}
		void clear() { 
			//a("c"); 
			indices_.clear(); 
		}

		void setValid(bool valid = true) { valid_ = valid; }
		bool isValid() const { return valid_; }
		void setInvalid(bool invalid = true) { valid_ = !invalid; }
		bool isInvalid() const { return !valid_; }

		bool operator==(const KeyMultiRecords<KeyType>& record) const {
			// Staci len rovost klucov resp. rovnost indexov nikdy ani nenastane
			// ak sa nebude porovnavat zaznam sam so sebou. Zaznamy vsak musia 
			// mat rovnake hodnoty pokial maju rovnake kluce pozicia v tabulke
			// nie je dolezita hlavne ze sa dostanem na tie iste data (hodnoty).
			return key_ == record.key_;
		}

	private:
		KeyType key_;
		IndexContainer indices_;
		/// Invalidita zaznamu. Zaznam obsahuje 0..n indexov. V algoritmoch sa 
		/// vyuziva aj 0, ktora je validnym stavom. Pokial ma byt zaznam odmazany
		/// a vlastniaca struktura bud nepodporuje mazanie alebo ma odlozene 
		/// mazanie tak sa prvok oznamci ako invalidny.
		bool valid_;

	//	std::string actBuff_;
	};

	template<typename T>
	std::ostream& operator<<(std::ostream &out, const jm4bbx::KeyRecord<T>& x) {
		out << "rec(row=" << x.getIndex() << ",key=" << x.getKey() << ") ";
		return out;
	}


	struct BinaryOperationResultIndex {
		size_t firstTableRowIndex_;
		size_t secondTableRowIndex_;
	};


	std::ostream& operator<<(std::ostream &out, const jm4bbx::BinaryOperationResultIndex& x);

#ifdef BOBOX_VERSION_OLD 

	typedef bobox::parameters plainParameters;
	typedef bobox::basic_box2 basicBox;
	typedef bobox::inarc_index_type inType;
	typedef bobox::outarc_index_type outType;

	typedef bobox::int_policy::value_type integerType;
	typedef bobox::string_policy::value_type stringType;
	typedef KeyRecord<int> IntegerKeyRecord;
	typedef KeyRecord<std::string> StringKeyRecord;
	typedef BinaryOperationResultIndex BinaryOperationResultIndexType;

	// Policy su zavedene len kvoli kompatibilite s predoslou verziou boboxu.
	// V akutualnej staci pouzivat priamo typy vid integerType a stringType
	typedef bobox::int_policy integerPolicyType;
	typedef bobox::string_policy stringPolicyType;

	struct IntegerKeyRecordPolicyType : bobox::generic_object_policy<IntegerKeyRecord> {
		static inline std::string get_name() { return "IntegerKeyRecord"; }
	};

	struct StringKeyRecordPolicyType : bobox::generic_object_policy<StringKeyRecord> {
		static inline std::string get_name() { return "StringKeyRecord"; }
	};

	struct BinaryOperationResultIndexPolicyType : bobox::generic_object_policy<StringKeyRecord> {
		static inline std::string get_name() { return "BinaryOperationResultIndex"; }
	};
#endif
#ifdef BOBOX_VERSION_2_2
	typedef bobox::parameters_ptr_type plainParameters;
	typedef bobox::group_box basicBox;
	typedef bobox::input_index_type inType;
	typedef bobox::output_index_type outType;

	typedef int integerType;
	typedef std::string stringType;
	typedef KeyRecord<int> IntegerKeyRecord;
	typedef KeyRecord<std::string> StringKeyRecord;
	typedef BinaryOperationResultIndex BinaryOperationResultIndexType;
	// Policy su zavedene len kvoli kompatibilite s predoslou verziou boboxu.
	// V akutualnej staci pouzivat priamo typy vid integerType a stringType
	typedef int integerPolicyType;
	typedef std::string stringPolicyType;
	typedef IntegerKeyRecord IntegerKeyRecordPolicyType;
	typedef StringKeyRecord StringKeyRecordPolicyType;
	typedef BinaryOperationResultIndex BinaryOperationResultIndexPolicyType;

	//template<typename T>
	//std::ostream& operator<<(std::ostream &out, const jm4bbx::BinaryOperationResultIndexPolicyType& x) {
	//	out << x.firstTableRowIndex_ << " : " << x.secondTableRowIndex_ ;
	//	return out;
	//}

	//template<typename T>
	//std::ostream& operator<<(std::ostream &out, const jm4bbx::BinaryOperationResultIndexType& x) {
	//	out << x.firstTableRowIndex_ << " : " << x.secondTableRowIndex_ ;
	//	return out;
	//}

#endif

	typedef basicBox::group_index_type groupType;
	typedef bobox::column_index_type columnType;
} // namespace jm4bbx


#endif
